/* sxpdiv64.c - 64 bits unsigned and signed integer division */

/*
 * Copyright (c) 2007 Wind River Systems, Inc.
 *
 * The right to copy, distribute, modify or otherwise make use
 * of this software may be licensed only pursuant to the terms
 * of an applicable Wind River license agreement.
 */

/*
modification history
--------------------
01c,03oct07,mat Fixed APIGen comment for __divdi3 to have correct name, and
                fixed indenting to match coding standard
01b,12sep07,dan Made changes to meet WRS coding standard - WIND00104341
01a,13aug07,dan Added  "modification history" and made text changes - WIND00098657
*/

#define M_div64
/**************	Imported modules ********************************/

#define ulonglong unsigned long long
#define slonglong signed long long

/**************	Local data, types, fns and macros ***************/
/*
#ifdef	__DCC__
static ulonglong div64(ulonglong, ulonglong);
#else
static ulonglong div64();
#endif
*/
/**************************************************
* div64 - Perform 64 bits unsigned integer division.
* Divides 'j' by 'k'
* 
* RETURNS: 64 bits unsigned integer
*
*/

static ulonglong div64
    (
    ulonglong j,
    ulonglong k
    )
    {
    slonglong i, m;
    ulonglong n;
    unsigned int c;

    if (((k-1) & k) == 0)
        {
        /* Divide by power of 2. */
        n = j;
        if((k & 0x00000000ffffffffll) == 0)
            {
            k >>= 32;
            n >>= 32;
            }
        c = k;
        if((c & 0xffff) == 0)
            {
            c >>= 16;
            n >>= 16;
            }
        if((c & 0xff) == 0)
            {
            c >>= 8;
            n >>= 8;
            }
        while (c >>= 1)
            {
            n >>= 1;
            }
        }
    else if(((m = j | k) & 0xffffffff00000000ll) == 0)
        {
        n = (unsigned int)j/(unsigned int)k;
	}
    else
        {
        i = 0xff00000000000000ll;
        if ((m & i) == 0)
            {
            i >>= 8;
            if ((m & i) == 0)
                {
                i >>= 8;
                if ((m & i) == 0)
                    {
                    i >>= 8;
                    }
                }
            }
        c = 0;
        while ((k & i) == 0)
            {
            k <<= 8;
            c += 8;
            }
        if(j & 0x8000000000000000ll)
            {
            while ((k & 0x8000000000000000ll) == 0)
                {
                k <<= 1;
                c++;
                }
            n = 0;
            if (j >= k)
                {
                j -= k;
                n |= 1;
                }
            }
        else
            {
            while (k <= j)
                {
                k <<= 1;
                c++;
                }
            n = 0;
            }
        while (c-- > 0)
            {
            k >>= 1;
            n <<= 1;
            if (j >= k)
                {
                j -= k;
                n |= 1;
                }
            }
        }
    return n;
    }

/******************************************************
* __div64 - Perform 64 bits integer division.
* Divides 'j' by 'k'
*
* RETURNS: signed 64 bits integer
*
*/

slonglong __div64
    (
    ulonglong j,
    ulonglong k
    )
    {
    int s;
    ulonglong r;

    s = 0;
    if ((slonglong)j < 0)
        {
        j = -j;
        s ^= 1;
	}
    if ((slonglong)k <= 0)
        {
        if ((slonglong)k == 0)
            {
            return s ? 0x8000000000000000ll : 0x7fffffffffffffffll;
            }
        k = -k;
        s ^= 1;
	}
    r = div64(j, k);
    return s ? -r : r;
    }

/*********************************************************
 *	__udiv64 - Performs 64 bits unsigned integer division.
 * compute the result of the 64 bits division
 *
 * RETURNS:result of the unsigned division
 *
 */

ulonglong __udiv64
    (
    ulonglong j,
    ulonglong k
    )
    {
    if (k == 0)
        {
        return ~(ulonglong)0;
	}
    return div64(j, k);
    }

/* Local variables:     */
/* Mode: c-mode         */
/* c-indent-level: 8    */
/* c-argdecl-indent:0   */
/* c-label-offset: -8   */
/* comment-volumn: 40   */
/* End:                 */


/******************************************************
*
* __udivdi3 - unsigned 64 bits division
*
* computes the result of the 64 bits division
*
* RETURNS:result of the unsigned division
*
*/

#if 0
unsigned long long __udivdi3 
    (
    unsigned long long a,
    unsigned long long b
    )
    {
    
    return (__udiv64 (a,b));
    }

/******************************************************
*
* __divdi3 - signed 64 bits division
*
* compute the result of the 64 bits division
*
* RETURNS:result of the signed division
*
*/

signed long long __divdi3 
    (
    signed long long a,
    signed long long b
    )
    {
    
    return (__div64 (a,b));
    }

#endif


